﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Daco.Web.Publish
{
    public class CArticle : CBaseArticle
    {
        private string _articleID;
        public string ArticleID
        {
            get { return _articleID; }
            private set { _articleID = value; }
        }
        private int _categoryId = 0;
        public int CategoryId { get { return _categoryId; } set { _categoryId = value; } }
        private string _categoryTitle = "";
        public string CategoryTitle { get { return _categoryTitle; } set { _categoryTitle = value; } }
        private DateTime _addedDate = DateTime.Now;
        public DateTime AddedDate
        {
            get { return _addedDate; }
            set { _addedDate = value; }
        }
        private string _addedByName = "";
        public string AddedByName
        {
            get { return _addedByName; }
            set { _addedByName = value; }
        }
        private string _abstract = "";
        public string Abstract
        {
            get { return _abstract; }
            set { _abstract = value; }
        }
        private string _imageUrl = "";
        public string ImageUrl { get { return _imageUrl; } set { _imageUrl = value; } }
        private string _body = "";
        public string Body
        {
            get { return _body; }
            set { _body = value; }
        }
        private string _plainBody = "";
        public string PlainBody
        {
            get
            {
                if (_plainBody == "") _plainBody = Providers.CPublishProvider.Instance.GetArticleBody(this.ArticleID, true);
                return _plainBody;
            }
            set { _plainBody = value; }
        }
        private DateTime _releaseDate = DateTime.Now;
        public DateTime ReleaseDate
        {
            get { return _releaseDate; }
            set { _releaseDate = value; }
        }
        private DateTime _expireDate = DateTime.MaxValue;
        public DateTime ExpireDate
        {
            get { return _expireDate; }
            set { _expireDate = value; }
        }
        private bool _approved = true;
        public bool Approved
        {
            get { return _approved; }
            set { _approved = value; }
        }
        private bool _listed = true;
        public bool Listed
        {
            get { return _listed; }
            set { _listed = value; }
        }
        private bool _commentsEnabled = true;
        public bool CommentsEnabled
        {
            get { return _commentsEnabled; }
            set { _commentsEnabled = value; }
        }
        private bool _onlyForMembers = false;
        public bool OnlyForMembers
        {
            get { return _onlyForMembers; }
            set { _onlyForMembers = value; }
        }
        private int _viewCount = 0;
        public int ViewCount
        {
            get { return _viewCount; }
            set { _viewCount = value; }
        }
        private int _votes = 0;
        public int Votes
        {
            get { return _votes; }
            set { _votes = value; }
        }
        private int _totalRating = 0;
        public int TotalRating
        {
            get { return _totalRating; }
            private set { _totalRating = value; }
        }
        /// <summary>
        /// Gets the average rating.
        /// </summary>
        /// <value>The average rating.</value>
        public double AverageRating
        {
            get
            {
                if (this.Votes >= 1)
                    return ((double)this.TotalRating / (double)this.Votes);
                else
                    return 0D;
            }
        }

        /// <summary>
        /// Gets a value indicating whether this <see cref="CArticle"/> is published.
        /// </summary>
        /// <value><c>true</c> if published; otherwise, <c>false</c>.</value>
        public bool Published
        {
            get
            {
                return (this.Approved && this.ReleaseDate <= DateTime.Now && this.ExpireDate > DateTime.Now);
            }
        }

        public string RewriteUrl
        {
            get
            {
                return string.Format("~/Publish/Article,{0}.aspx", this.ArticleID);
            }
        }

        /// <summary>
        /// Increments the view count.
        /// </summary>
        public void IncrementViewCount()
        {
            ViewCount++;
        }

        /// <summary>
        /// Rates the specified rating.
        /// </summary>
        /// <param name="rating">The rating.</param>
        /// <returns></returns>
        public void Rate(int rating)
        {
            Votes++;
            TotalRating += rating;
        }

        public bool Delete() { bool success = CArticle.DeleteArticle(this.ArticleID); if (success) this.ArticleID = string.Empty; return success; }
        public bool Update() { return CArticle.UpdateArticle(this.ArticleID, this.CategoryId, this.Title, this.Abstract, this.ImageUrl, this.Body, this.ReleaseDate, this.ExpireDate, this.Approved, this.Listed, this.CommentsEnabled, this.OnlyForMembers); }
        public CArticle(string articleID, int categoryId, string categoryTitle, DateTime addedDate, string addedByName, string title, string a_abstract, string imageUrl, string body,
                DateTime releaseDate, DateTime expireDate, bool approved, bool listed, bool commentsEnabled, bool onlyForMembers, int viewCount, int votes, int totalRating)
        {
            this.ArticleID = articleID;
            this.CategoryId = categoryId;
            this.CategoryTitle = categoryTitle;
            this.ImageUrl = imageUrl;
            this.AddedDate = addedDate;
            this.AddedByName = addedByName;
            this.Title = title;
            this.Abstract = a_abstract;
            this.Body = body;
            this.ReleaseDate = releaseDate;
            this.ExpireDate = expireDate;
            this.Approved = approved;
            this.Listed = listed;
            this.CommentsEnabled = commentsEnabled;
            this.OnlyForMembers = onlyForMembers;
            this.ViewCount = viewCount;
            this.Votes = votes;
            this.TotalRating = totalRating;
        }

        /* -------------------------public static methods------------------------- */
        /// <summary>
        /// Return an CArticle object with the specified code or name
        /// </summary>
        /// <param name="isCode">determine what arcgrument is</param>
        public static CArticle GetArticle(string articleID)
        {
            string key = "IS_Articles_GetArticles_" + articleID;
            if (Config.CSiteConfig.Current.EnableCaching && CBizObject.Cache[key] != null)
                return (CArticle)CBizObject.Cache[key];
            else
            {
                CArticle ob = Providers.CPublishProvider.Instance.GetArticle(articleID);
                if (ob != null)
                {
                    if (Config.CSiteConfig.Current.EnableCaching) CBaseArticle.CacheData(key, ob);
                    return ob;
                }
                else return null;
            }
        }
        public static string GetArticleBody(string articleId, bool isPlainBody)
        {
            string key = "IS_Articles_GetArticleBody_" + articleId.ToString() + "_" + isPlainBody.ToString();
            if (Config.CSiteConfig.Current.EnableCaching && CBizObject.Cache[key] != null)
                return (string)CBizObject.Cache[key];
            else
            {
                string body = Providers.CPublishProvider.Instance.GetArticleBody(articleId, isPlainBody);
                CBaseArticle.CacheData(key, body);
                return body;
            }
        }
        /// <summary>
        /// Returns a collection with all articles
        /// </summary>
        public static List<CArticle> GetArticles() { return CArticle.GetArticles(0, CBizObject.MAXROWS); }
        /// <summary>
        /// Returns a collection with all articles
        /// </summary>
        public static List<CArticle> GetArticles(int pageIndex, int pageSize)
        {
            if (pageIndex < 1) pageIndex = 1;
            if (pageSize < Config.CSiteConfig.Current.DefaultPageSize) pageSize = Config.CSiteConfig.Current.DefaultPageSize;

            string key = "IS_Articles_GetArticles_" + pageIndex.ToString() + "_" + pageSize.ToString();
            if (Config.CSiteConfig.Current.EnableCaching && CBizObject.Cache[key] != null)
                return (List<CArticle>)CBizObject.Cache[key];
            else
            {
                List<CArticle> obs = Providers.CPublishProvider.Instance.GetArticles(pageIndex, pageSize);
                if (obs.Count > 0)
                {
                    if (Config.CSiteConfig.Current.EnableCaching) CBaseArticle.CacheData(key, obs);
                    return obs;
                }
                else return null;
            }
        }
        /// <summary>
        /// Returns a collection with all articles for the specified category
        /// </summary>
        public static List<CArticle> GetArticles(int categoryId) { return CArticle.GetArticles(categoryId, 1, CBizObject.MAXROWS); }
        /// <summary>
        /// Returns a collection with all articles for the specified category
        /// </summary>
        public static List<CArticle> GetArticles(int categoryId, int pageIndex, int pageSize)
        {
            if (pageIndex < 1) pageIndex = 1;
            if (pageSize < Config.CSiteConfig.Current.DefaultPageSize) pageSize = Config.CSiteConfig.Current.DefaultPageSize;

            string key = "IS_Articles_GetArticles_" + categoryId.ToString() + "_" + pageIndex.ToString() + "_" + pageSize.ToString();
            if (Config.CSiteConfig.Current.EnableCaching && CBizObject.Cache[key] != null)
                return (List<CArticle>)CBizObject.Cache[key];
            else
            {
                List<CArticle> obs = Providers.CPublishProvider.Instance.GetArticles(categoryId, pageIndex, pageSize);
                if (obs.Count > 0)
                {
                    if (Config.CSiteConfig.Current.EnableCaching) CBaseArticle.CacheData(key, obs);
                    return obs;
                }
                else return null;
            }
        }
        /// <summary>
        /// Returns a collection with all published articles
        /// </summary>
        public static List<CArticle> GetArticles(bool isPublishedOnly) { if (!isPublishedOnly) return CArticle.GetArticles(0, CBizObject.MAXROWS); else return CArticle.GetArticles(true, 1, CBizObject.MAXROWS); }
        /// <summary>
        /// Returns a collection with all published articles
        /// </summary>
        public static List<CArticle> GetArticles(bool isPublishedOnly, int pageIndex, int pageSize)
        {
            if (!isPublishedOnly) return CArticle.GetArticles(1, CBizObject.MAXROWS);
            else
            {
                if (pageIndex < 1) pageIndex = 1;
                if (pageSize < Config.CSiteConfig.Current.DefaultPageSize) pageSize = Config.CSiteConfig.Current.DefaultPageSize;

                string key = "IS_Articles_GetArticles_" + isPublishedOnly.ToString() + "_" + pageIndex.ToString() + "_" + pageSize.ToString();
                if (Config.CSiteConfig.Current.EnableCaching && CBizObject.Cache[key] != null)
                    return (List<CArticle>)CBizObject.Cache[key];
                else
                {
                    List<CArticle> obs = Providers.CPublishProvider.Instance.GetPublishedArticles(DateTime.Now, pageIndex, pageSize);
                    if (obs.Count > 0)
                    {
                        if (Config.CSiteConfig.Current.EnableCaching) CBaseArticle.CacheData(key, obs);
                        return obs;
                    }
                    else return null;
                }
            }
        }
        /// <summary>
        /// Returns a collection with all published articles for the specified category
        /// </summary>
        public static List<CArticle> GetArticles(bool isPublishedOnly, int categoryId) { if (!isPublishedOnly) return CArticle.GetArticles(categoryId, 0, CBizObject.MAXROWS); else return CArticle.GetArticles(true, categoryId, 0, CBizObject.MAXROWS); }
        /// <summary>
        /// Returns a collection with all published articles for the specified category
        /// </summary>
        public static List<CArticle> GetArticles(bool isPublishedOnly, int categoryId, int pageIndex, int pageSize)
        {
            if (!isPublishedOnly) return CArticle.GetArticles(categoryId, 0, CBizObject.MAXROWS);
            else
            {
                if (categoryId <= 0) return CArticle.GetArticles(true, 0, CBizObject.MAXROWS);
                else
                {
                    if (pageIndex < 1) pageIndex = 1;
                    if (pageSize < Config.CSiteConfig.Current.DefaultPageSize) pageSize = Config.CSiteConfig.Current.DefaultPageSize;

                    string key = "IS_Articles_GetArticles_" + isPublishedOnly.ToString() + "_" + categoryId.ToString() + "_" + pageIndex.ToString() + "_" + pageSize.ToString();
                    if (Config.CSiteConfig.Current.EnableCaching && CBizObject.Cache[key] != null)
                        return (List<CArticle>)CBizObject.Cache[key];
                    else
                    {
                        List<CArticle> obs = Providers.CPublishProvider.Instance.GetPublishedArticles(categoryId, DateTime.Now, pageIndex, pageSize);
                        if (obs.Count > 0)
                        {
                            if (Config.CSiteConfig.Current.EnableCaching) CBaseArticle.CacheData(key, obs);
                            return obs;
                        }
                        else return null;
                    }
                }
            }
        }
        /// <summary>
        /// Returns a collection with all published related articles for the specified current article
        /// </summary>
        public static List<CArticle> GetRelatedArticles(string articleId, int count)
        {
            string key = "IS_Articles_GetRelatedArticles_" + articleId.ToString() + "_" + count.ToString();
            if (Config.CSiteConfig.Current.EnableCaching && CBizObject.Cache[key] != null)
                return (List<CArticle>)CBizObject.Cache[key];
            else
            {
                List<CArticle> obs = Providers.CPublishProvider.Instance.GetRelatedArticles(articleId, count);
                if (obs.Count > 0)
                {
                    if (Config.CSiteConfig.Current.EnableCaching) CBaseArticle.CacheData(key, obs);
                    return obs;
                }
                else return null;
            }
        }
        /// <summary>
        /// Returns the number of total articles
        /// </summary>
        public static int GetArticleCount() { string key = "IS_Articles_GetArticleCount_"; if (Config.CSiteConfig.Current.EnableCaching && CBizObject.Cache[key] != null) return (int)CBizObject.Cache[key]; int count = Providers.CPublishProvider.Instance.GetArticleCount(); if (Config.CSiteConfig.Current.EnableCaching) CBaseArticle.CacheData(key, count); return count; }
        /// <summary>
        /// Returns the number of total published articles
        /// </summary>
        public static int GetArticleCount(bool isPublishedOnly) { if (!isPublishedOnly)return CArticle.GetArticleCount(); else { string key = "IS_Articles_GetArticleCount_" + isPublishedOnly.ToString(); if (Config.CSiteConfig.Current.EnableCaching && CBizObject.Cache[key] != null) return (int)CBizObject.Cache[key]; int count = Providers.CPublishProvider.Instance.GetPublishedArticleCount(DateTime.Now); if (Config.CSiteConfig.Current.EnableCaching) CBaseArticle.CacheData(key, count); return count; } }
        /// <summary>
        /// Returns the number of total articles for the specified category
        /// </summary>
        public static int GetArticleCount(int categoryId) { string key = "IS_Articles_GetArticleCount_" + categoryId.ToString(); if (Config.CSiteConfig.Current.EnableCaching && CBizObject.Cache[key] != null) return (int)CBizObject.Cache[key]; int count = Providers.CPublishProvider.Instance.GetArticleCount(categoryId); if (Config.CSiteConfig.Current.EnableCaching) CBaseArticle.CacheData(key, count); return count; }
        /// <summary>
        /// Returns the number of total published articles for the specified category
        /// </summary>
        public static int GetArticleCount(bool isPublishedOnly, int categoryId) { if (!isPublishedOnly) return CArticle.GetArticleCount(categoryId); else { string key = "IS_Articles_GetArticleCount_" + isPublishedOnly.ToString(); if (Config.CSiteConfig.Current.EnableCaching && CBizObject.Cache[key] != null) return (int)CBizObject.Cache[key]; int count = Providers.CPublishProvider.Instance.GetPublishedArticleCount(categoryId, DateTime.Now); if (Config.CSiteConfig.Current.EnableCaching) CBaseArticle.CacheData(key, count); return count; } }
        /// <summary>
        /// Approves an existing article
        /// </summary>
        public static bool ApproveArticle(string articleId)
        {
            bool success = Providers.CPublishProvider.Instance.ApproveArticle(articleId);
            if (success) { CBizObject.PurgeCacheItems("IS_Articles_GetArticle_" + articleId.ToString()); CBizObject.PurgeCacheItems("IS_Articles_GetArticles_"); }
            return success;
        }
        /// <summary>
        /// Increments an article's view count
        /// </summary>
        public static bool RateArticle(string articleId, int rating) { return Providers.CPublishProvider.Instance.RateArticle(articleId, rating); }
        /// <summary>
        /// Increments an article's view count
        /// </summary>
        public static bool IncrementViewCount(string articleId) { return Providers.CPublishProvider.Instance.IncrementArticleViewCount(articleId); }
        /// <summary>
        /// Insert new CArticle
        /// </summary>
        public static int InsertArticle(int categoryId, string title, string aabstract, string imageUrl, string body, DateTime releaseDate, DateTime expireDate, bool approved, bool listed, bool commentsEnabled, bool onlyForMembers)
        {
            //bool canApprove = CBizObject.CurrentUser.IsInRole("Administrators") || CBizObject.CurrentUser.IsInRole("Managers") || CBizObject.CurrentUser.IsInRole("Editors");
            if (releaseDate > DateTime.Now) listed = true;
            if (expireDate <= releaseDate) expireDate = DateTime.MaxValue;
            //int articleId = Providers.CPublishProvider.Instance.InsertArticle(new ArticleDetails(0, categoryId, "", code, DateTime.Now, DateTime.Now, CBizObject.CurrentUser.Identity.Name, baseName, title, aabstract, imageUrl, body, "", releaseDate, expireDate, canApprove, listed, commentsEnabled, onlyForMembers, 0, 0, 0, ""));
            //if (articleId > 0) CBizObject.PurgeCacheItems("IS_Articles_GetArticle");
            //return articleId;
            return 0;
        }
        /// <summary>
        /// Update an existing article
        /// </summary>
        public static bool UpdateArticle(string articleId, int categoryId, string title, string aabstract, string imageUrl, string body, DateTime releaseDate, DateTime expireDate, bool approved, bool listed, bool commentsEnabled, bool onlyForMembers)
        {
            //bool canApprove = CBizObject.CurrentUser.IsInRole("Administrators") || CBizObject.CurrentUser.IsInRole("Managers") || CBizObject.CurrentUser.IsInRole("Editors");
            //if (releaseDate > DateTime.Now) listed = true;
            //if (expireDate <= releaseDate) expireDate = DateTime.MaxValue;
            //bool success = Providers.CPublishProvider.Instance.UpdateArticle(new ArticleDetails(articleId, categoryId, "", "", DateTime.Now, DateTime.Now, CBizObject.CurrentUser.Identity.Name, basename, title, aabstract, imageUrl, body, "", releaseDate, expireDate, canApprove, listed, commentsEnabled, onlyForMembers, 0, 0, 0, ""));
            //if (success) CBizObject.PurgeCacheItems("IS_Articles_GetArticles");
            //return success;

            return false;
        }
        /// <summary>
        /// Delete an existing article
        /// </summary>
        public static bool DeleteArticle(string articleId)
        {
            //bool success = Providers.CPublishProvider.Instance.DeleteArticle(articleId);
            //if (success)
            //{
            //    CBizObject.PurgeCacheItems("IS_Articles_GetArticle");
            //    new RecordDeletedEvent("CArticle", articleId, null).Raise();
            //}
            //return success;

            return false;
        }
    }
}
